import des, dt

AS_LIST = [["ship","attributes","weapon"], 
        ["ship","outfits"],
        ["ship","attributes","licenses"]]

class Render():

    def __init__(self, fname):
        self._fname = fname
        self._ship = None
        self._thead = None

    def _create_thead(self):
        def visit_attr(thead, node, parent_path):
            child_head = thead.append_sub(node.Key)
            node_path = parent_path[:]
            node_path.append(node.Key)
            if len(node) > 0 and node_path not in AS_LIST:
                for ele in node:
                    visit_attr(child_head, ele, node_path)
        self._thead = dt.THead('root')
        for ship in self._ships:
            visit_attr(self._thead, ship, [])
        self._thead = self._thead[0]
        self._thead.reindex(0, 0)

    def _print_thead(self):
        def recu_print(thead, indent):
            print("%s%s, (%d,%d)" % 
                    ('  ' * indent, thead.Content, thead.X, thead.Y))
            if len(thead) > 0:
                for h in thead:
                    recu_print(h, indent + 1)
        recu_print(self._thead, 0)

    def _get_x(self, path):
        thead = self._thead
        for ele in path:
            for col in thead:
                if col.Content == ele:
                    thead = col
                    break
        return thead.X

    def _render_tbody(self):
        def fill_cell(retn, offset, value):
            while len(retn) <= offset:
                retn.append(None)
            origin_val = retn[offset]
            if origin_val is None:
                retn[offset] = value
            elif isinstance(origin_val, list):
                origin_val.append(value)
            else:
                retn[offset] = [origin_val, value]
        def render_node(node, parent_path, retn):
            node_path = parent_path[:]
            node_path.append(node.Key)
            x = self._get_x(node_path)
            if node_path in AS_LIST:
                val = []
                for ele in node:
                    val.append("%s %s" % (ele.Key, ele.Value))
                fill_cell(retn, x, val)
            else:
                fill_cell(retn, x, node.Value)
                for child in node:
                    render_node(child, node_path, retn)
        html = []
        for ship in self._ships:
            html.append('<tr>')
            tds = []
            render_node(ship, [], tds)
            for td in tds:
                html.append('<td>')
                if td is None:
                    pass
                elif isinstance(td, list):
                    html.append("<p>")
                    html.append('</p><p>'.join(td))
                    html.append("</p>")
                else:
                    html.append(td)
                html.append('</td>')
            html.append('</tr>')
        return ''.join(html)

    def main(self):

        self._ships = des.read_data_file(self._fname)
        '''
        |Ship
        |    |sprite      |attributes
        |    |            |          |category          |cost   |...
        |-----------------------------------------------------------
        |Aeri|"ship/aerie"|          | "Medium Warship" |3500000|...
        '''
        # create thead
        '''
        {
          "ship": {
            "sprite": None,
            "attributes": {
              "category": None,
              "cost": None
            }
            ...
          }
        }
        '''
        self._create_thead()
        self._print_thead()
        html = []
        stack = [self._thead]
        while len(stack) > 0:
            next_level = []
            tr = []
            for th in stack:
                if th is None: # if indent
                    tr.append("<td></td>")
                    next_level.append(None) # keep indent to next row
                    continue
                tr.append("<td colspan=%d>%s</td>" % 
                        (th.get_span(), th.Content))
                if len(th) > 0:
                    next_level.append(None) # append a indent
                    for ele in th:
                        next_level.append(ele)
            tr.insert(0, "<tr>")
            tr.append("</tr>")
            html.extend(tr)
            if next_level.count(None) == len(next_level):
                break
            stack = next_level
        html.append(self._render_tbody())
        print("<html><body><table border=2>")
        print(''.join(html))
        print("</table></body></html>")

if __name__ == "__main__":
    render = Render('data/ships.txt')
    render.main()




